﻿/***************************************************************
 * 开发人员：网魂小兵@http://www.mozlite.com
 * 
 * 缓存键锁列表管理类。
 * 
 * 最后修改：2011-10-28
 * ************************************************************/
namespace Mozlite.Caching
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Web.Caching;

    internal class CacheLockbox
    {
        private static readonly Dictionary<string, CacheEntry> lockbox = new Dictionary<string, CacheEntry>();
        private static readonly object readLocker = new object();
        private static readonly object writeLocker = new object();

        private CacheLockbox()
        {
        }

        public static bool ContainsCacheEntry(string key)
        {
            return lockbox.ContainsKey(key);
        }

        public static CacheEntry GetCacheEntry(string key)
        {
            lock (readLocker)
            {
                if (ContainsCacheEntry(key))
                {
                    return lockbox[key];
                }
                return null;
            }
        }

        public static object GetInternalLock(string key)
        {
            lock (readLocker)
            {
                CacheEntry entry = null;
                if (ContainsCacheEntry(key))
                {
                    entry = lockbox[key];
                }
                if (entry != null)
                {
                    return entry.InternalLocker;
                }
                return null;
            }
        }

        public static object GetLock(string key)
        {
            lock (readLocker)
            {
                CacheEntry entry = null;
                if (ContainsCacheEntry(key))
                    entry = lockbox[key];
                if (entry != null)
                {
                    entry.LastUse = DateTime.UtcNow;
                    return entry.Locker;
                }
                throw new Exception("CacheEntry for key '" + key + "' doesn't exist.  Please call GetLock(string key, TimeSpan refreshInterval, TimeSpan refreshDuration, CacheItemPriority priority, Cacher.CacheLoaderDelegate cacheLoader) to set a CacheEntry.");
            }
        }

        public static object GetLock(string key, TimeSpan refreshInterval, TimeSpan slidingExpiration, CacheLoaderDelegate cacheLoader, CacheItemPriority priority = CacheItemPriority.Normal)
        {
            lock (readLocker)
            {
                CacheEntry entry;
                if (ContainsCacheEntry(key))
                {
                    entry = lockbox[key];
                    entry.LastUse = DateTime.UtcNow;
                    if (entry.CacheLoader == null)
                        entry.CacheLoader = cacheLoader;
                }
                else
                {
                    lock (writeLocker)
                    {
                        entry = new CacheEntry();
                        entry.CacheLoader = cacheLoader;
                        entry.RefreshInterval = refreshInterval;
                        entry.SlidingExpiration = slidingExpiration;
                        entry.CacheItemPriority = priority;
                        entry.LastUse = DateTime.UtcNow;
                        lockbox.Add(key, entry);
                    }
                }
                return entry.Locker;
            }
        }

        public static void UpdateCacheEntryLastUpdate(string key, DateTime lastUpdate)
        {
            lock (writeLocker)
            {
                if (ContainsCacheEntry(key))
                {
                    CacheEntry entry = lockbox[key];
                    entry.LastUpdate = lastUpdate;
                }
            }
        }

        public static void UpdateCacheEntryLastUse(string key, DateTime lastUse)
        {
            lock (writeLocker)
            {
                if (ContainsCacheEntry(key))
                {
                    CacheEntry entry = lockbox[key];
                    entry.LastUse = lastUse;
                }
            }
        }

        public static Dictionary<string, CacheEntry>.KeyCollection Keys
        {
            get
            {
                return lockbox.Keys;
            }
        }

        public static bool Remove(string key)
        {
            lock (readLocker)
            {
                if (ContainsCacheEntry(key))
                {
                    lock (writeLocker)
                    {
                        return lockbox.Remove(key);
                    }
                }
            }
            return false;
        }

    }
}
